<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.3">
<title>Spring Cloud Contract with Rest Docs 2.1.3.BUILD-SNAPSHOT</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
/* Remove comment around @import statement below when using as a custom stylesheet */
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
audio,canvas,video{display:inline-block}
audio:not([controls]){display:none;height:0}
[hidden],template{display:none}
script{display:none!important}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
body{margin:0}
a{background:transparent}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
abbr[title]{border-bottom:1px dotted}
b,strong{font-weight:bold}
dfn{font-style:italic}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
body{-webkit-font-smoothing:antialiased}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.center{margin-left:auto;margin-right:auto}
.spread{width:100%}
p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:none}
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.no-bullet{list-style:none}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
abbr{text-transform:none}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
blockquote cite:before{content:"\2014 \0020"}
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
table thead,table tfoot{background:#f7f8f7;font-weight:bold}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
body{tab-size:4}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
.clearfix:after,.float-group:after{clear:both}
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menu{color:rgba(0,0,0,.8)}
b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}
b.button:before{content:"[";padding:0 3px 0 2px}
b.button:after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}
#header:after,#content:after,#footnotes:after,#footer:after{clear:both}
#content{margin-top:1.25em}
#content:before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span:before{content:"\00a0\2013\00a0"}
#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark:before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber:after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media only screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
.sect1{padding-bottom:.625em}
@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}
.sect1+.sect1{border-top:1px solid #efefed}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}
.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.listingblock>.content{position:relative}
.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
.listingblock:hover code[data-lang]:before{display:block}
.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}
.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
table.pyhltable td.code{padding-left:.75em;padding-right:0}
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
pre.pygments .lineno{display:inline-block;margin-right:.25em}
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
.quoteblock .quoteblock blockquote:before{display:none}
.verseblock{margin:0 1em 1.25em 1em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract{margin:0 0 1.25em 0;display:block}
.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
table.tableblock{max-width:100%;border-collapse:separate}
table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot{border-width:1px 0}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
td>div.verse{white-space:pre}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em}
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px}
ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
ul.inline>li>*{display:block}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist>table tr>td:first-of-type{padding:0 .75em;line-height:1}
.colist>table tr>td:last-of-type{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
.gist .file-data>table td.line-data{width:99%}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background-color:#00fafa}
.black{color:#000}
.black-background{background-color:#000}
.blue{color:#0000bf}
.blue-background{background-color:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background-color:#fa00fa}
.gray{color:#606060}
.gray-background{background-color:#7d7d7d}
.green{color:#006000}
.green-background{background-color:#007d00}
.lime{color:#00bf00}
.lime-background{background-color:#00fa00}
.maroon{color:#600000}
.maroon-background{background-color:#7d0000}
.navy{color:#000060}
.navy-background{background-color:#00007d}
.olive{color:#606000}
.olive-background{background-color:#7d7d00}
.purple{color:#600060}
.purple-background{background-color:#7d007d}
.red{color:#bf0000}
.red-background{background-color:#fa0000}
.silver{color:#909090}
.silver-background{background-color:#bcbcbc}
.teal{color:#006060}
.teal-background{background-color:#007d7d}
.white{color:#bfbfbf}
.white-background{background-color:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background-color:#fafa00}
span.icon>.fa{cursor:default}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]:after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@media print{@page{margin:1.25cm .75cm}
*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]:after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
.sect1{padding-bottom:0!important}
.sect1+.sect1{border:0!important}
#header>h1:first-child{margin-top:1.25rem}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span:before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]:before{display:block}
#footer{background:none!important;padding:0 .9375em}
#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
</style>
<style>
.hidden {
	display: none;
}

.switch {
	border-width: 1px 1px 0 1px;
	border-style: solid;
	border-color: #7a2518;
	display: inline-block;
}

.switch--item {
	padding: 10px;
	background-color: #ffffff;
	color: #7a2518;
	display: inline-block;
	cursor: pointer;
}

.switch--item.selected {
	background-color: #7a2519;
	color: #ffffff;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
<script type="text/javascript">
function addBlockSwitches() {
	$('.primary').each(function() {
		primary = $(this);
		createSwitchItem(primary, createBlockSwitch(primary)).item.addClass("selected");
		primary.children('.title').remove();
	});
	$('.secondary').each(function(idx, node) {
		secondary = $(node);
		primary = findPrimary(secondary);
		switchItem = createSwitchItem(secondary, primary.children('.switch'));
		switchItem.content.addClass('hidden');
		findPrimary(secondary).append(switchItem.content);
		secondary.remove();
	});
}

function createBlockSwitch(primary) {
	blockSwitch = $('<div class="switch"></div>');
	primary.prepend(blockSwitch);
	return blockSwitch;
}

function findPrimary(secondary) {
	candidate = secondary.prev();
	while (!candidate.is('.primary')) {
		candidate = candidate.prev();
	}
	return candidate;
}

function createSwitchItem(block, blockSwitch) {
	blockName = block.children('.title').text();
	content = block.children('.content').first().append(block.next('.colist'));
	item = $('<div class="switch--item">' + blockName + '</div>');
	item.on('click', '', content, function(e) {
		$(this).addClass('selected');
		$(this).siblings().removeClass('selected');
		e.data.siblings('.content').addClass('hidden');
		e.data.removeClass('hidden');
	});
	blockSwitch.append(item);
	return {'item': item, 'content': content};
}

$(addBlockSwitches);
</script>
</head>

<body class="article toc2 toc-left">
<div id="header">
<h1>Spring Cloud Contract with Rest Docs 2.1.3.BUILD-SNAPSHOT</h1>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_scenarios">Scenarios</a></li>
<li><a href="#_flow">Flow</a></li>
<li><a href="#_tutorial">Tutorial</a>
<ul class="sectlevel2">
<li><a href="#_producer_flow_1">Producer flow 1</a>
<ul class="sectlevel3">
<li><a href="#_ide_setup_for_the_producer_scenario">IDE Setup for the Producer Scenario</a></li>
<li><a href="#_adding_dependencies_to_the_producer_s_code">Adding Dependencies to the Producer&#8217;s Code</a></li>
<li><a href="#_setting_up_the_spring_cloud_contract_plugin_assembly_plugin">Setting up the Spring Cloud Contract Plugin &amp; Assembly Plugin</a></li>
<li><a href="#_writing_your_first_rest_docs_test">Writing Your First Rest Docs Test</a></li>
<li><a href="#_defining_the_first_messaging_contract">Defining the First Messaging Contract</a></li>
<li><a href="#_defining_the_second_messaging_contract">Defining the Second Messaging Contract</a></li>
<li><a href="#_generating_tests_from_contracts">Generating Tests from Contracts</a></li>
<li><a href="#_fixing_broken_messaging_tests">Fixing broken messaging tests</a></li>
<li><a href="#_writing_the_missing_producer_messaging_implementation">Writing the missing producer messaging implementation</a></li>
<li><a href="#_checking_the_generated_jar_file">Checking the Generated JAR File</a></li>
</ul>
</li>
<li><a href="#_consumer_flow_2">Consumer Flow 2</a>
<ul class="sectlevel3">
<li><a href="#_adding_spring_cloud_contract">Adding Spring Cloud Contract</a></li>
<li><a href="#contract-workshop-reading-http-stubs-from-classpath">Reading HTTP Stubs from the Classpath with Spring Cloud Contract WireMock</a></li>
<li><a href="#contract-workshop-reading-http-stubs-from-classpath-stubrunner">Reading HTTP Stubs from the Classpath with Spring Cloud Contract Stub Runner</a></li>
<li><a href="#contract-workshop-writing-missing-consumer-messaging">Writing the Missing Consumer Messaging Implementation</a></li>
<li><a href="#contract-workshop-reading-messaging-stubs-stubrunner">Reading Messaging Stubs with the Spring Cloud Contract Stub Runner</a></li>
<li><a href="#contract-workshop-reading-messaging-stubs-classpath">Reading Messaging Stubs from the Classpath with Spring Cloud Contract Stub Runner</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#_solutions">Solutions</a>
<ul class="sectlevel2">
<li><a href="#_written_consumer_tests">Written consumer tests</a></li>
<li><a href="#_adding_spring_cloud_contract_dependency">Adding Spring Cloud Contract Dependency</a></li>
<li><a href="#_proposal_of_simple_contracts_by_consumer">Proposal of simple contracts by consumer</a></li>
<li><a href="#_missing_consumer_controller_code">Missing consumer controller code</a></li>
<li><a href="#_stub_logs">Stub Logs</a></li>
<li><a href="#_beer_request">Beer Request</a></li>
<li><a href="#_missing_listener_code">Missing listener code</a></li>
<li><a href="#_missing_triggers">Missing triggers</a></li>
<li><a href="#_messaging_dsls">Messaging DSLs</a></li>
<li><a href="#_producercontroller_implementation">ProducerController implementation</a></li>
<li><a href="#_beerrestbase">BeerRestBase</a></li>
<li><a href="#_beermessagingbase">BeerMessagingBase</a></li>
<li><a href="#_messaging_implementation">Messaging implementation</a></li>
<li><a href="#_rest_docs_producer_tests_config">Rest Docs Producer Tests Config</a></li>
<li><a href="#_rest_docs_producer_tests">Rest Docs Producer Tests</a></li>
<li><a href="#_rest_docs_producer_tests_with_contracts">Rest Docs Producer Tests with Contracts</a></li>
</ul>
</li>
<li><a href="#_back_to_the_main_page">Back to the Main Page</a></li>
</ul>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>In this tutorial, we&#8217;ll combine messaging contracts from the producer side with
generating stubs from Spring Rest Docs.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_scenarios">Scenarios</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In most of the tutorials, you will be asked to code the following scenarios:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/beer_1.png" alt="beer 1">
</div>
<div class="title">Figure 1. Positive beer selling via HTTP</div>
</div>
<div class="paragraph">
<p>&#160;
&#160;</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/beer_2.png" alt="beer 2">
</div>
<div class="title">Figure 2. Negative beer selling via HTTP</div>
</div>
<div class="paragraph">
<p>&#160;
&#160;</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/msg_1.png" alt="msg 1">
</div>
<div class="title">Figure 3. Positive age verification via messaging</div>
</div>
<div class="paragraph">
<p>&#160;
&#160;</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/msg_2.png" alt="msg 2">
</div>
<div class="title">Figure 4. Negative age verification via messaging</div>
</div>
<div class="paragraph">
<p>&#160;
&#160;</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_flow">Flow</h2>
<div class="sectionbody">
<div class="imageblock">
<div class="content">
<img src="../images/rest_docs_flow.png" alt="rest docs flow">
</div>
<div class="title">Figure 5. Producer Contract flow</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_tutorial">Tutorial</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This time, the producer defines the contracts and generates stubs. This is typically
the case when your application has many consumers and it would be very difficult to
take every consumer&#8217;s opinion into account.</p>
</div>
<div class="sect2">
<h3 id="_producer_flow_1">Producer flow 1</h3>
<div class="imageblock">
<div class="content">
<img src="../images/rest_docs_producer_flow.png" alt="rest docs producer flow">
</div>
<div class="title">Figure 6. Producer declares contracts and writes Rest Docs tests</div>
</div>
<div class="sect3">
<h4 id="_ide_setup_for_the_producer_scenario">IDE Setup for the Producer Scenario</h4>
<div class="paragraph">
<p>To set up your IDE for this tutorial:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>In your IDE, open the <code>producer_with_restdocs</code> project (via either Maven or Gradle).</p>
</li>
<li>
<p>Add the necessary dependencies, as shown in the next section.</p>
</li>
</ol>
</div>
</div>
<div class="sect3">
<h4 id="_adding_dependencies_to_the_producer_s_code">Adding Dependencies to the Producer&#8217;s Code</h4>
<div class="paragraph">
<p>We&#8217;ll use Rest Docs with Spring Cloud Contract to generate HTTP stubs, and
we&#8217;ll write the DSL contracts for messaging. In order to add Rest Docs, add the following
test dependencies:</p>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.restdocs&lt;/groupId&gt;
    &lt;artifactId&gt;spring-restdocs-mockmvc&lt;/artifactId&gt;
    &lt;optional&gt;true&lt;/optional&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testCompile("org.springframework.restdocs:spring-restdocs-mockmvc")</code></pre>
</div>
</div>
<div class="paragraph">
<p>In order to use Spring Cloud Contract Rest Docs integration, you have to add the
<code>spring-cloud-contract-wiremock</code> dependency. That way, we can generate the
<a href="http://wiremock.org">WireMock</a> stubs from our Rest Docs tests.</p>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-contract-wiremock&lt;/artifactId&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testCompile("org.springframework.cloud:spring-cloud-contract-wiremock")</code></pre>
</div>
</div>
<div class="paragraph">
<p>To get the IDE to help us with code completion in writing DSL contracts, we can add the
necessary Spring Cloud Contract dependencies. You need to add
<code>spring-cloud-starter-contract-verifier</code> as a test dependency</p>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
	&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
	&lt;artifactId&gt;spring-cloud-starter-contract-verifier&lt;/artifactId&gt;
	&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testCompile("org.springframework.cloud:spring-cloud-starter-contract-verifier")</code></pre>
</div>
</div>
<div class="paragraph">
<p>You need to this task only once, because, when you add contracts, all the dependencies
are already added.</p>
</div>
</div>
<div class="sect3">
<h4 id="_setting_up_the_spring_cloud_contract_plugin_assembly_plugin">Setting up the Spring Cloud Contract Plugin &amp; Assembly Plugin</h4>
<div class="paragraph">
<p>We need to use both the Spring Cloud Contract plugin &amp; the assembly plugin. We use the
Spring Cloud Contract plugin to generate tests for messaging contracts. We use the
Assembly plugin to generate the JAR that holds the messaging contracts and HTTP stubs.</p>
</div>
<div class="paragraph">
<p>Spring Cloud Contract can generate tests from your contracts to ensure that your
implementation&#8217;s API is compatible with the defined contract. Let&#8217;s set up the project to
start generating messaging tests.</p>
</div>
<div class="paragraph">
<p>By default, Spring Cloud Contract plugin creates the  JAR  with stubs. We need to disable
that behavior.</p>
</div>
<div class="paragraph">
<p>Spring Cloud Contract needs a base class that all of the generated tests extend.
Currently, we support three different ways of defining a base class (you can read more
about this in the Spring Cloud Contract documentation for
<a href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_configure_plugin">Gradle</a>
and
<a href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_configure_plugin_2">Maven</a>):</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A single class for all tests.</p>
</li>
<li>
<p>Convention-based naming (which takes the last two package names and appends <code>Base</code>. For
example, a contract <code>src/test/resources/contracts/foo/bar/shouldDoSth.groovy</code> creates a
test class called <code>BarTest</code> that would extend the <code>FooBarBase</code> class.</p>
</li>
<li>
<p>Manual mapping (you can state that contracts matching certain regular expressions must
have a base class with fully qualified name equal to the value you specify).</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>In the following example, we use convention-based naming. For Maven, under the plugin
setup, you must set up the plugin configuration as follows:
<code>&lt;configuration&gt;&lt;packageWithBaseClasses&gt;com.example&lt;/packageWithBaseClasses&gt;&lt;/configuration&gt;</code></p>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;properties&gt;
    &lt;!-- we don't want the spring cloud contract plugin to do a jar for us --&gt;
    &lt;spring.cloud.contract.verifier.skip&gt;true&lt;/spring.cloud.contract.verifier.skip&gt;
&lt;/properties&gt;
&lt;plugins&gt;
    &lt;plugin&gt;
        &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
        &lt;artifactId&gt;spring-cloud-contract-maven-plugin&lt;/artifactId&gt;
        &lt;version&gt;${spring-cloud-contract.version}&lt;/version&gt;
        &lt;extensions&gt;true&lt;/extensions&gt;
        &lt;configuration&gt;
            &lt;packageWithBaseClasses&gt;com.example&lt;/packageWithBaseClasses&gt;
        &lt;/configuration&gt;
    &lt;/plugin&gt;
    &lt;!-- we want the assembly plugin to generate the JAR --&gt;
    &lt;plugin&gt;
        &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
        &lt;artifactId&gt;maven-assembly-plugin&lt;/artifactId&gt;
        &lt;executions&gt;
            &lt;execution&gt;
                &lt;id&gt;stub&lt;/id&gt;
                &lt;phase&gt;prepare-package&lt;/phase&gt;
                &lt;goals&gt;
                    &lt;goal&gt;single&lt;/goal&gt;
                &lt;/goals&gt;
                &lt;inherited&gt;false&lt;/inherited&gt;
                &lt;configuration&gt;
                    &lt;attach&gt;true&lt;/attach&gt;
                    &lt;descriptor&gt;${basedir}/src/assembly/stub.xml&lt;/descriptor&gt;
                &lt;/configuration&gt;
            &lt;/execution&gt;
        &lt;/executions&gt;
    &lt;/plugin&gt;
&lt;/plugins&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">contracts {
    packageWithBaseClasses = 'com.example'
}
task stubsJar(type: Jar) {
	classifier = "stubs"
	into('/') {
		include('**/com/example/model/*.*')
		from("${project.rootDir}/src/main/java/")
	}
	into('/') {
		include('**/com/example/model/*.*')
		from("${project.buildDir}/classes/main")
	}
	into("META-INF/${project.group}/${project.name}/${project.version}/mappings") {
		include('**/*.*')
		from("${project.rootDir}/target/snippets/stubs")
	}
	into("META-INF/${project.group}/${project.name}/${project.version}/contracts") {
		include('**/*.groovy')
		from("${project.rootDir}/src/test/resources/contracts")
	}
}
// we need the tests to pass to build the stub jar
stubsJar.dependsOn(test)
// we want to disable the default Spring Cloud Contract stub jar generation
verifierStubsJar.enabled = false

artifacts {
	archives stubsJar
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>In both cases, passing that value tells the plugin that a given base class is available
under the <code>com.example</code> package. Also, it creates a stub jar in a custom way. For Maven,
it uses the assembly plugin with the configuration defined under <code>src/assembly/stub.xml</code>.
For Gradle, it uses the assembly plugin through the <code>stubsJar</code> task. The stubs jar
contains:
* The classes and sources of the POJO models.
* The contracts, under
<code>META-INF/${project.group}/${project.name}/${project.version}/contracts</code>.
* The stubs, under
<code>META-INF/${project.group}/${project.name}/${project.version}/mappings</code>.</p>
</div>
<div class="paragraph">
<p>An example for <code>com.example:beer-producer:0.0.1.BUILD-SNAPSHOT</code> would be
<code>META-INF/com.example/beer-producer/0.0.1.BUILD-SNAPSHOT/contracts</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="_writing_your_first_rest_docs_test">Writing Your First Rest Docs Test</h4>
<div class="paragraph">
<p>Open the <code>ProducerController</code> class. You can see that we already prepared some basic
setup for you. Our controller accepts a JSON request with a <code>PersonToCheck</code> body and
returns a JSON response of <code>Response</code> type. The logic that checks whether a person is
eligible to get beer is done via the <code>PersonCheckingService</code> interface.</p>
</div>
<div class="paragraph">
<p>We want to do TDD on the producer side, so let&#8217;s start with a test. To do so, open the
<code>ProducerControllerTests</code> class. We need to add the Rest Docs support by annotating the
class in the following way:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@AutoConfigureRestDocs(outputDir = "target/snippets")</code></pre>
</div>
</div>
<div class="paragraph">
<p>That way, any snippets produced by Rest Docs end up in the <code>target/snippets</code> folder. We
need to write two tests - one for the client who is old enough and one for a client
who is too young.</p>
</div>
<div class="paragraph">
<p>As you can see, we set up the Spring context. Doing so requires a fake
implementation of the <code>PersonCheckingService</code>, since we don&#8217;t want to access any
databases, send messages, and so on. To do that in the <code>Config</code> class, at the bottom of
the test, you can register a bean of <code>PersonCheckingService</code> type that returns <code>true</code>
when the age of the <code>PersonToCheck</code> is greater than or equal to <code>20</code>.
(<a href="#_rest_docs_producer_test_config">Show solution</a>)</p>
</div>
<div class="paragraph">
<p>We use MockMvc to send a JSON request to the <code>/check</code> endpoint. The body of the request
is the prepared <code>PersonToCheck</code> object (hint: you can use the prepared <code>JacksonTester</code>
object to send that <code>json</code>. In the response, for the positive scenario, we expect the
response to set the <code>status</code> field equal to <code>OK</code>
(hint: <code>.andExpect(jsonPath("$.status").value("OK")))</code>
and set the <code>status</code> field for for the negative scenario equal to <code>NOT_OK</code> (hint:
<code>.andExpect(jsonPath("$.status").value("NOT_OK")))</code>.
(<a href="#_rest_docs_producer_tests">Show solution</a>)</p>
</div>
<div class="paragraph">
<p>Let&#8217;s run the tests. They fail because we have yet to write any implementation on the
producer side. Let&#8217;s fix that.</p>
</div>
<div class="paragraph">
<p>In the <code>ProducerController</code> class, write the missing implementation. If the
<code>PersonCheckingService</code> returns <code>true</code> when the <code>PersonToCheck</code> is eligible to get beer,
then return the <code>Response</code> with <code>BeerCheckStatus</code> equal to <code>OK</code>. Otherwise, the
<code>BeerCheckStatus</code> should equal <code>NOT_OK</code>.
(<a href="#_producerController_implementation">Show solution</a>)</p>
</div>
<div class="paragraph">
<p>Let&#8217;s rerun the tests. Now they should pass. We have yet to create any stubs. It&#8217;s time
to fix that.</p>
</div>
<div class="paragraph">
<p>Spring Cloud Contract WireMock comes with a handy method called
<code>WireMockRestDocs.verify()</code> that you can pass to the Rest Doc&#8217;s <code>andDo()</code> method. The
<code>WireMockRestDocs.verify()</code> method lets you:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Register the request and the response to store it as stub.</p>
</li>
<li>
<p>Assert JSON path&#8217;s of the request via <code>jsonPath</code> method (that&#8217;s how you can check the
dynamic bits of your response).</p>
</li>
<li>
<p>Check the content type of the request via the <code>contentType()</code> method.</p>
</li>
<li>
<p>Save the stored request and response information as a WireMock stub via <code>stub()</code>
method.</p>
</li>
<li>
<p>Access WireMock&#8217;s API to perform further request verification via the <code>wiremock()</code>
method.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Spring Cloud Contract WireMock also comes with a
<code>SpringCloudContractRestDocs.dslContract()</code> method that lets you generate a DSL contract
from your Rest Docs tests. This can be handy when you have a lot of Rest Docs tests and
would like to migrate to DSL tests. If you call the <code>andDo()</code> method and pass to it the
<code>MockMvcRestDocumentation.document(&#8230;&#8203;,&#8230;&#8203;)</code>, you&#8217;ll create a <code>dsl-contract.adoc</code> file
under the <code>target/snippets/shouldRejectABeerIfTooYoung</code> folder and
<code>shouldRejectABeerIfTooYoung.groovy</code> file under the <code>target/snippets/contracts/</code> folder.
The code to do so follows:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">.andDo(MockMvcRestDocumentation
    .document("shouldRejectABeerIfTooYoung", SpringCloudContractRestDocs.dslContract()));</code></pre>
</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
To make this work, you must first call the <code>WireMockRestDocs.verify()</code> method
and <strong>only after</strong> that call the <code>SpringCloudContractRestDocs.dslContract()</code> method.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Now you can add the Spring Cloud Contract Rest Docs support, as
(<a href="#__rest_docs_producer_tests_with_contracts">shown here</a>). To do so:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>For the positive scenario, assert that the <code>age</code> is greater or equal to <code>20</code> (hint: the
JSON path for this check is <code>$[?(@.age &gt;= 20)]</code>).</p>
</li>
<li>
<p>For the negative scenario, assert that the <code>age</code> is less than <code>20</code> (hint: the JSON path
for this check is <code>$[?(@.age &lt; 20)]</code>)</p>
</li>
<li>
<p>Assert that the request header contains a <code>content-type</code> of <code>applicaton/json</code> (hint:
you can use the <code>MediaType</code> method: <code>MediaType.valueOf("application/json")</code>).</p>
</li>
<li>
<p>Produce the stub and <code>shouldGrantABeerIfOldEnough</code> the its documentation called for the
positive scenario.</p>
</li>
<li>
<p>Produce the stub called <code>shouldRejectABeerIfTooYoung</code> and its DSL documentation for the
negative scenario.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Congratulations! In your <code>target/snippets</code> you should see:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>contracts/shouldGrantABeerIfOldEnough.groovy</code>, which is a file with the DSL contract
for the positive scenario.</p>
</li>
<li>
<p><code>contracts/target/snippets/.groovy</code>, which is a file with the DSL contract for the
negative scenario.  // TODO Missing file name?</p>
</li>
<li>
<p><code>shouldGrantABeerIfOldEnough/</code>, which is a folder with <code>adoc</code> files containing
documentation of the positive scenario.</p>
</li>
<li>
<p><code>shouldRejectABeerIfTooYoung/</code>, which is a folder with <code>adoc</code> files containing
documentation of the negative scenario.</p>
</li>
<li>
<p><code>stubs/shouldGrantABeerIfOldEnough.json</code>, which is a WireMock stub of the positive
scenario.</p>
</li>
<li>
<p><code>stubs/shouldRejectABeerIfTooYoung.json</code>, which is a WireMock stub of the negative
scenario.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Now we xan define the messaging contracts.</p>
</div>
</div>
<div class="sect3">
<h4 id="_defining_the_first_messaging_contract">Defining the First Messaging Contract</h4>
<div class="paragraph">
<p>We&#8217;ve done the case for HTTP. Now we can move to the
<code>src/test/resources/contracts/beer/messaging</code> folder.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Time to define some contracts for messaging. Create a <code>shouldSendAcceptedVerification.groovy</code> file. If you&#8217;re lost just check out the <a href="#_proposal_of_simple_contracts_by_consumer">solution</a></p>
<div class="ulist">
<ul>
<li>
<p>Call the <code>org.springframework.cloud.contract.spec.Contract.make { }</code> method to start defining the contract</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
}</code></pre>
</div>
</div>
</li>
<li>
<p>You can call <code>description()</code> method to provide some meaningful description. TIP: You can use the
Groovy multiline String <code>""" """</code> to have all special characters escaped. Every new line in the String
will be converted into a new line character</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
}</code></pre>
</div>
</div>
</li>
<li>
<p>HTTP communication is synchronous - you send a request and you get a response. With messaging the situation
is different - a consumer suddenly might get a message. In the consumer tests the consumer needs a mean to
trigger that message. That hook is called a <code>label</code> in Spring Cloud Contract. Let&#8217;s call our label
<code>accepted_verification</code>. To define it in the contract just call the <code>label</code> method like this
<code>label 'accepted_verification'</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    label "accepted_verification"
}</code></pre>
</div>
</div>
</li>
<li>
<p>Next we define the message that we would like to receive. So from the producer&#8217;s perspective that&#8217;s an
<code>outputMessage</code>. You can call that message in the Groovy DSL <code>outputMessage { }</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    label "accepted_verification"
    outputMessage {

    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>Inside that method we need to define where and what we want to send. Let&#8217;s start with the first.
You can call the <code>sentTo</code> method and provide the destination. According to the requirements we want
to send the message to the <code>verifications</code> channel. Let&#8217;s define that in the contract
by calling <code>sentTo 'verifications'</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    label "accepted_verification"
    outputMessage {
        sentTo "verifications"
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>As for the body we just can call <code>body(eligible: true)</code>. That way we&#8217;ll send a JSON body via messaging</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    label "accepted_verification"
    outputMessage {
        sentTo "verifications"
        body(eligible: true)
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>We can also set headers on the message. Let&#8217;s call <code>headers { }</code> method and inside the closure we can set an
explicit header. In case of messaging with Spring Cloud Stream, a header that describes the content
type of the payload is called <code>contentType</code>. So we need to set it like this
<code>header("contentType", applicationJsonUtf8())</code>.</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    label "accepted_verification"
    outputMessage {
        sentTo "verifications"
        body(eligible: true)
        headers {
            header("contentType", applicationJsonUtf8())
        }
    }
}</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>We need to modify the messaging contracts cause they are missing one important piece from the
producer&#8217;s perspective - the <code>input</code> part</p>
<div class="ulist">
<ul>
<li>
<p>In case of messaging there has to be some trigger that will result in producing an output message</p>
</li>
<li>
<p>Spring Cloud Contract accepts 3 situations</p>
<div class="ulist">
<ul>
<li>
<p>Input message produces an output message</p>
</li>
<li>
<p>A method execution produces an output message</p>
</li>
<li>
<p>Input message doesn&#8217;t produce any output message</p>
</li>
</ul>
</div>
</li>
<li>
<p>In our situation we&#8217;ll have a method produce an output. It&#8217;s enough to pass the <code>input {}</code> method
and then the <code>triggeredBy</code> method. The <code>triggeredBy</code> method requires a String with a method execution.
So if in the base class we expect to have a method called <code>triggerSomeMessage()</code> that would trigger a message
for tests, then we would write <code>input { triggeredBy("triggerSomeMessage()") }</code> to make this happen. Example:</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    label "accepted_verification"
    input {
        triggeredBy("triggerSomeMessage()")
    }
    outputMessage {
        sentTo "verifications"
        body(eligible: true)
        headers {
            header("contentType", applicationJsonUtf8())
        }
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>For this workshop for the <code>shouldSendAcceptedVerification.groovy</code> we want to trigger the <code>clientIsOldEnough()</code>
    method and for <code>shouldSendRejectedVerification.groovy</code> we want to trigger the <code>clientIsTooYoung()</code> method
from the base class. (<a href="#_messaging_dsls">Show solution</a>)</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_defining_the_second_messaging_contract">Defining the Second Messaging Contract</h4>
<div class="paragraph">
<p>Now you can create the second contract. Create a file called <code>shouldSendRejectedVerification.groovy</code>.
If you get lost, check out the <a href="#_proposal_of_simple_contracts_by_consumer">solution</a>. To
create the contract:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Set the <code>eligible</code> property in the response body to <code>false</code>.</p>
</li>
<li>
<p>Update the label to <code>rejected_verification</code>.</p>
</li>
<li>
<p>Update the description.</p>
</li>
</ol>
</div>
</div>
<div class="sect3">
<h4 id="_generating_tests_from_contracts">Generating Tests from Contracts</h4>
<div class="paragraph">
<p>Now we can generate the tests. To do so, call:</p>
</div>
<div class="paragraph">
<p>+</p>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./mvnw clean install</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./gradlew clean build publishToMavenLocal</code></pre>
</div>
</div>
<div class="paragraph">
<p>Suddenly some tests should start failing. Those tests are the autogenerated tests created
by Spring Cloud Contract. The tests are under the
<code>/generated-test-sources/contracts/org/springframework/cloud/contract/verifier/tests/beer</code>
directory in the <code>target</code> directory for Maven or the <code>build</code> directory for Gradle.
There is a test for each folder in which you store your contracts. The name of the test
class is the name of that folder.</p>
</div>
</div>
<div class="sect3">
<h4 id="_fixing_broken_messaging_tests">Fixing broken messaging tests</h4>
<div class="ulist">
<ul>
<li>
<p>Now let&#8217;s go to the messaging part.</p>
</li>
<li>
<p>Let&#8217;s check out the <code>src/main/resources/application.yml</code> file whether it contains the proper
destination set for <code>spring.cloud.stream.bindings.output.destination</code>. If not then let&#8217;s set it
to <code>verifications</code> - this is the queue / topic we&#8217;d like to receive the message from</p>
</li>
<li>
<p>We&#8217;re trying to do TDD so let&#8217;s move to <code>BeerMessagingBase</code> test class. The first thing we need to do is to
add the <code>@AutoConfigureMessageVerifier</code> annotation on the test class. That will configure
the setup related to messaging and Spring Cloud Contract.</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@AutoConfigureMessageVerifier
public abstract class BeerMessagingBase {
...
}</code></pre>
</div>
</div>
</li>
<li>
<p>We need to prepare some setup for our tests. To do that we&#8217;ll need to clear any remaining
messages that could break our tests. To do that we&#8217;ll use the Spring Cloud Contract <code>MessageVerifier</code>
abstraction (it allows to send and receive messages from e.g. Spring Cloud Stream, Sprig Integration, Apache Camel.)</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@AutoConfigureMessageVerifier
public abstract class BeerMessagingBase {
    @Inject MessageVerifier messaging;
	@Autowired PersonCheckingService personCheckingService;

	@Before
	public void setup() {
		// let's clear any remaining messages
		// output == destination or channel name
		this.messaging.receive("output", 100, TimeUnit.MILLISECONDS);
	}

	public void clientIsOldEnough() {
    }

    public void clientIsTooYoung() {
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>In the <code>clientIsOldEnough()</code> and <code>clientIsTooYoung()</code> we need the logic to trigger a message.
What triggers a message will be the implementation of the <code>PersonCheckingService#shouldGetBeer</code>.</p>
</li>
<li>
<p>For <code>clientIsOldEnough()</code> we can use a <code>PersonToCheck</code> of age <code>25</code> for example and
<code>clientIsTooYoung</code> can have age <code>5</code>. (<a href="#_beermessagingbase">Show solution</a>)</p>
</li>
<li>
<p>We can run the test which will obviously fail because we have a missing implementation. Let&#8217;s move
to <code>AgeCheckingPersonCheckingService</code></p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_writing_the_missing_producer_messaging_implementation">Writing the missing producer messaging implementation</h4>
<div class="ulist">
<ul>
<li>
<p>We need to check if the person&#8217;s age is greater or equal to 20 - if that&#8217;s the case then the
we need to send the properly generated <code>Verification</code> object. In order to send a message you can use the
following code <code>source.output().send(MessageBuilder.withPayload(new Verification(true)).build())</code>.
In this case we&#8217;re sending a message to the <code>output</code> channel (that is bound to <code>verifications</code> destination).
(<a href="#_messaging_implementation">Show solution</a>)</p>
</li>
<li>
<p>Let&#8217;s run the tests again - they should all pass!</p>
</li>
<li>
<p>Now let&#8217;s ensure that we can successfully publish artifacts to Maven local</p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./mvnw clean install</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./gradlew clean build publishToMavenLocal</code></pre>
</div>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_checking_the_generated_jar_file">Checking the Generated JAR File</h4>
<div class="paragraph">
<p>Let&#8217;s check out what&#8217;s inside the generated stub JAR. Assuming that our configuration is
OK, if you run the following command, you should see output that resembles the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ unzip -l target/beer-api-producer-restdocs-0.0.1-SNAPSHOT-stubs.jar
Archive:  beer-api-producer-restdocs-0.0.1-SNAPSHOT-stubs.jar
  Length      Date    Time    Name
---------  ---------- -----   ----
      164  2016-11-10 08:34   com/example/model/PersonToCheck.java
        0  2017-05-12 13:40   META-INF/com.example/beer-api-producer-restdocs/
        0  2017-05-12 13:40   META-INF/com.example/beer-api-producer-restdocs/0.0.1-SNAPSHOT/mappings/
      569  2017-05-12 13:40   META-INF/com.example/beer-api-producer-restdocs/0.0.1-SNAPSHOT/mappings/shouldRejectABeerIfTooYoung.json
      157  2016-11-10 08:34   com/example/model/Response.java
      423  2017-05-12 13:40   com/example/model/PersonToCheck.class
        0  2017-05-12 13:40   META-INF/
      414  2017-05-12 13:40   com/example/model/Response.class
        0  2017-05-12 13:40   com/example/model/
     1015  2017-05-12 13:40   com/example/model/BeerCheckStatus.class
       71  2016-11-10 08:34   com/example/model/BeerCheckStatus.java
        0  2017-05-12 13:40   META-INF/com.example/beer-api-producer-restdocs/0.0.1-SNAPSHOT/contracts/
        0  2017-05-12 13:40   META-INF/com.example/beer-api-producer-restdocs/0.0.1-SNAPSHOT/contracts/beer/
        0  2017-05-12 13:40   META-INF/com.example/beer-api-producer-restdocs/0.0.1-SNAPSHOT/contracts/beer/messaging/
      742  2017-05-12 13:38   META-INF/com.example/beer-api-producer-restdocs/0.0.1-SNAPSHOT/contracts/beer/messaging/shouldSendAcceptedVerification.groovy
        0  2017-05-12 13:40   com/
      595  2017-05-12 13:40   com/example/model/Verification.class
      105  2017-05-12 13:40   META-INF/MANIFEST.MF
      309  2016-11-10 08:34   com/example/model/Verification.java
        0  2017-05-12 13:40   com/example/
        0  2017-05-12 13:40   META-INF/com.example/
        0  2017-05-12 13:40   META-INF/com.example/beer-api-producer-restdocs/0.0.1-SNAPSHOT/
      566  2017-05-12 13:40   META-INF/com.example/beer-api-producer-restdocs/0.0.1-SNAPSHOT/mappings/shouldGrantABeerIfOldEnough.json
      745  2017-05-12 13:38   META-INF/com.example/beer-api-producer-restdocs/0.0.1-SNAPSHOT/contracts/beer/messaging/shouldSendRejectedVerification.groovy
---------                     -------
     5875                     24 files</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Under <code>com/example/model</code>, you can see the compiled POJOs with sources.</p>
</li>
<li>
<p>Under <code>META-INF/com.example/beer-api-producer-restdocs/0.0.1-SNAPSHOT/contracts</code>, you
can see the messaging contracts.</p>
</li>
<li>
<p>Under <code>META-INF/com.example/beer-api-producer-restdocs/0.0.1-SNAPSHOT/mappings</code>, you
can see all the generated HTTP stubs.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>In a "real life" scenario, we would merge our code into a fat jar, and a jar with stubs
would be generated by the CI system. In this tutorial, we work with our Maven local, so
that we don&#8217;t have to do anything else.</p>
</div>
<div class="paragraph">
<p>Now we can move to the consumer side.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_consumer_flow_2">Consumer Flow 2</h3>
<div class="imageblock">
<div class="content">
<img src="../images/consumer_flow_2.png" alt="consumer flow 2">
</div>
<div class="title">Figure 7. Online work with stubs</div>
</div>
<div class="paragraph">
<p>In this part of the tutorial, we show different ways of working with stubs:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Using the <code>@AutoConfigureWireMock</code> annotation to manually pass a list of stubs to
register from the classpath.</p>
</li>
<li>
<p>Using the <code>@AutoConfigureStubRunner</code> annotation with classpath scanning.</p>
</li>
<li>
<p>Using the <code>@AutoConfigureStubRunner</code> annotation for offline work</p>
</li>
</ul>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
This feature is available as of the Spring Cloud Contract 1.1.1.RELEASE.
</td>
</tr>
</table>
</div>
<div class="sect3">
<h4 id="_adding_spring_cloud_contract">Adding Spring Cloud Contract</h4>
<div class="paragraph">
<p>To add Spring Cloud Contract, we&#8217;ll do each of the following:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#contract-workshop-reading-http-stubs-from-classpath-wiremock">[contract-workshop-reading-http-stubs-from-classpath-wiremock]</a></p>
</li>
<li>
<p><a href="#contract-workshop-reading-http-stubs-from-classpath-stubrunner">Reading HTTP Stubs from the Classpath with Spring Cloud Contract Stub Runner</a></p>
</li>
<li>
<p><a href="#contract-workshop-writing-missing-consumer-messaging">Writing the Missing Consumer Messaging Implementation</a></p>
</li>
<li>
<p><a href="#contract-workshop-reading-messaging-stubs-stubrunner">Reading Messaging Stubs with the Spring Cloud Contract Stub Runner</a></p>
</li>
<li>
<p><a href="#contract-workshop-reading-messaging-stubs-classpath">Reading Messaging Stubs from the Classpath with Spring Cloud Contract Stub Runner</a></p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="contract-workshop-reading-http-stubs-from-classpath">Reading HTTP Stubs from the Classpath with Spring Cloud Contract WireMock</h4>
<div class="paragraph">
<p>In your IDE, open the consumer code from the <code>consumer_with_restdocs</code> directory. We want
to do TDD, so let&#8217;s open the <code>BeerControllerTest</code> class.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>We have two objectives for HTTP</p>
<div class="ulist">
<ul>
<li>
<p>when a client wants a beer and has
e.g. name "marcin" and age 22 - the answer that we&#8217;ll respond with <code>THERE YOU GO</code></p>
</li>
<li>
<p>when a client is an underage and wants a beer and has
e.g. name "marcin" and age 17 - the answer that we&#8217;ll respond with <code>GET LOST</code></p>
</li>
</ul>
</div>
</li>
<li>
<p>and we have two objectives for messaging</p>
<div class="ulist">
<ul>
<li>
<p>when a verification message with <code>eligible</code> field equal to <code>true</code> was sent to the <code>verifications</code> channel
then we increment the <code>eligible</code> counter</p>
</li>
<li>
<p>when a verification message with <code>eligible</code> field equal to <code>false</code> was sent to the <code>verifications</code> channel
then we increment the <code>notEligible</code> counter</p>
</li>
</ul>
</div>
</li>
<li>
<p>Let&#8217;s start with HTTP.</p>
</li>
<li>
<p>Open the <code>BeerControllerTest</code> test. Since CDC is like TDD we have 2 tests that describe our beer selling features.
and we&#8217;re already providing some basic setup for you (in real TDD
example you&#8217;d have to code all of that yourself)</p>
</li>
<li>
<p>Technically speaking for both cases we want to use <code>MockMvc</code> to send a request to the <code>/beer</code> endpoint
with a JSON pojo containing <code>name</code> and <code>age</code>. From the controller we want to send a request to
<code><a href="http://localhost:8090/" class="bare">http://localhost:8090/</a></code> where the producer will be waiting for out requests. Let&#8217;s write the missing
tests body. (<a href="#_written_consumer_tests">Show solution</a>)</p>
</li>
<li>
<p>The first step in TDD is <code>red</code> - let&#8217;s run the tests and ensure that they are failing (in the controller
we return <code>null</code> instead of any meaningful value)</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Since the producer has already published its stubs, we already know how the API looks.
Let&#8217;s write the missing implementation for the <code>BeerController</code>.
(<a href="#_missing_consumer_controller_code">Show solution</a>)</p>
</div>
<div class="paragraph">
<p>If we run our tests again, they fail due to <code>Connection Refused</code>. That&#8217;s because we try
to send a request to a non-started server.</p>
</div>
<div class="paragraph">
<p>Now you can turn on the magic! To do so, add the Spring Cloud Starter Contract Stub
Runner test dependency.</p>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
	&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
	&lt;artifactId&gt;spring-cloud-starter-contract-stub-runner&lt;/artifactId&gt;
	&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testCompile("org.springframework.cloud:spring-cloud-starter-contract-stub-runner")</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Now we&#8217;ll add the producer stub dependency to our project</p>
</li>
</ul>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
    &lt;groupId&gt;com.example&lt;/groupId&gt;
    &lt;artifactId&gt;beer-api-producer-restdocs&lt;/artifactId&gt;
    &lt;classifier&gt;stubs&lt;/classifier&gt;
    &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
    &lt;exclusions&gt;
        &lt;exclusion&gt;
            &lt;groupId&gt;*&lt;/groupId&gt;
            &lt;artifactId&gt;*&lt;/artifactId&gt;
        &lt;/exclusion&gt;
    &lt;/exclusions&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testCompile("com.example:beer-api-producer-restdocs:0.0.1-SNAPSHOT:stubs") {
    transitive = false
}</code></pre>
</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
Remember not to include any transitive dependencies. We want to import only
the JAR that contains the contracts and stubs.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Now we can annotate the <code>BeerControllerTest</code> class with
<code>@AutoConfigureWireMock(stubs = "classpath:/META-INF/com.example/beer-api-producer-restdocs/<strong>*/</strong>.json", port = 8090)</code></p>
</div>
<div class="paragraph">
<p>That annotation tells WireMock to start a fake HTTP server at port <code>8090</code> and to register
all stubs at the following location:</p>
</div>
<div class="paragraph">
<p><code>/META-INF/com.example/beer-api-producer-restdocs/<strong>*/</strong>.json</code> on the classpath</p>
</div>
<div class="paragraph">
<p>Let&#8217;s run our tests again. Now they should pass!</p>
</div>
</div>
<div class="sect3">
<h4 id="contract-workshop-reading-http-stubs-from-classpath-stubrunner">Reading HTTP Stubs from the Classpath with Spring Cloud Contract Stub Runner</h4>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
This feature is available as of the 1.1.1.RELEASE version.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>This part assumes that you have done the previous task so that your consumer project is
properly set up.</p>
</div>
<div class="paragraph">
<p>To read the stubs:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Open the <code>BeerControllerClasspathTest</code>. We use Stub Runner to pick stubs from the
classpath.</p>
</li>
<li>
<p>Now annotate the class with
<code>@AutoConfigureStubRunner(ids = "com.example:beer-api-producer-restdocs:+:8090", stubsMode = StubRunnerProperties.StubsMode.CLASSPATH)</code></p>
</li>
<li>
<p>Run the tests and you can see them pass!</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>For this example, we scan the following locations by default:
* <code>/META-INF/com.example/beer-api-producer-restdocs/<strong>/<strong>.</strong></code>
* <code>/contracts/com.example/beer-api-producer-restdocs/</strong>/<strong>.</strong></code>
* <code>/mappings/com.example/beer-api-producer-restdocs/<strong>*/</strong>.*</code></p>
</div>
</div>
<div class="sect3">
<h4 id="contract-workshop-writing-missing-consumer-messaging">Writing the Missing Consumer Messaging Implementation</h4>
<div class="ulist">
<ul>
<li>
<p>We&#8217;ve gone through the HTTP scenario and now it&#8217;s time for the messaging part.</p>
</li>
<li>
<p>Let' start with a test as usual. Let&#8217;s check out the <code>BeerVerificationListenerTest</code> test class</p>
<div class="ulist">
<ul>
<li>
<p>there are 2 test methods with empty bodies</p>
</li>
<li>
<p>in both cases we need to trigger a message that will get sent to a destination at which our
listener class is awaiting messages</p>
</li>
<li>
<p>we&#8217;re missing the triggering part - but we&#8217;ll add it in a second</p>
</li>
</ul>
</div>
</li>
<li>
<p>On the consumer side let&#8217;s check out the <code>BeerVerificationListener</code> class.</p>
<div class="ulist">
<ul>
<li>
<p>We&#8217;re using the Spring Cloud Stream&#8217;s abstraction of a queue / topic which is called a <code>channel</code>.</p>
</li>
<li>
<p>There are 2 channels that come out od the box with SC-Stream. These are <code>input</code> and <code>output</code>.
Those channels can be found in 2 interfaces - <code>Sink</code> and <code>Source</code>. <code>Sink</code> contains the <code>input</code> channel
which is used for listening for messages and <code>Source</code> contains the <code>output</code> channel which
is used to send messages. In the listener class you can see that we use the <code>Sink</code> one cause we&#8217;re waiting for
a message to be received.</p>
</li>
<li>
<p>We have to configure the <code>destination</code>, so the actual name of a queue / topic on which we will be
listening. To do that you have to set in the <code>src/main/resources/application.yml</code> the property
<code>spring.cloud.stream.bindings.input.destination: verifications</code>. That means that the we&#8217;ll use the
<code>input</code> channel (so the channel in the <code>Sink</code> interface) to listen to messages coming from a
destination called <code>verifications</code>.</p>
</li>
<li>
<p>Now that we have configured Spring Cloud Stream let&#8217;s write the missing feature. If the <code>eligible</code> flag
in the incoming message is <code>true</code> - increase the <code>eligibleCounter</code> value. Otherwise increment the
other <code>notEligibleCounter</code> one. (<a href="#_missing_listener_code">Show solution</a>)</p>
</li>
</ul>
</div>
</li>
<li>
<p>Now that the implementation is written - let&#8217;s try to run our <code>BeerVerificationListenerTest</code> tests.
Unfortunately they will fail cause no message has been received - we&#8217;ll still missing that part</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="contract-workshop-reading-messaging-stubs-stubrunner">Reading Messaging Stubs with the Spring Cloud Contract Stub Runner</h4>
<div class="paragraph">
<p>Since Rest Docs have nothing to do with messaging, we must use the standard Stub Runner
approach:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Time to use Spring Cloud Contract!</p>
<div class="ulist">
<ul>
<li>
<p>We need to use Spring Cloud Contract Stub Runner so that it downloads the stubs. Just add the
<code>@AutoConfigureStubRunner(stubsMode = StubRunnerProperties.StubsMode.LOCAL, ids = "com.example:beer-api-producer-restdocs")</code> to download
the latest stubs of <code>com.example:beer-api-producer-restdocs</code>, with classifier <code>stubs</code> and if the JAR
contains any HTTP stubs then register them at a random port.</p>
</li>
<li>
<p>Now we need a solution to trigger the message. To do that we need to autowire a <code>StubTrigger</code> interface.
Just add <code>@Autowired StubTrigger stubTrigger</code> field to your test</p>
</li>
<li>
<p>In the contract on the producer side we&#8217;ve described 2 labels. <code>accepted_verification</code> and <code>rejected_verification</code>.
You can use the <code>StubTrigger#trigger</code> method to trigger a message with a given label. For example
if you call <code>stubTrigger.trigger("accepted_verification")</code> you&#8217;ll trigger a message that got described
with the <code>accepted_verification</code> label.</p>
</li>
<li>
<p>Now add the missing <code>StubTrigger#tigger</code> method in the test bodies. (<a href="#_missing_triggers">Show solution</a>)</p>
</li>
<li>
<p>Run the tests and they should pass!</p>
</li>
<li>
<p>You can change the <code>destination</code> name in <code>src/main/resources/application.yml</code> to <code>foo</code> and rerun the
tests - you&#8217;ll see that they&#8217;ll start failing. That&#8217;s because you&#8217;re listening to messages
at destination <code>foo</code> whereas the message is sent to <code>verifications</code></p>
</li>
<li>
<p>You can also play around with the <code>Verification</code> payload class. If you change the field name from
<code>eligible</code> to <code>foo</code> an rerun the tests - the tests will fail. If you change the type from <code>boolean</code>
to <code>Integer</code> (and change the production code too) then the tests will fail due to serialization problems</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="contract-workshop-reading-messaging-stubs-classpath">Reading Messaging Stubs from the Classpath with Spring Cloud Contract Stub Runner</h4>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
This feature is available as of the 1.1.1.RELEASE version
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Now that you have written the implementation and have tested it in the previous section,
we can try to read the message stubs from classpath. To do so, annotate the
<code>BeerVerificationListenerClasspathTest</code> class with
<code>@AutoConfigureStubRunner(ids = "com.example:beer-api-producer-restdocs:+:8090", stubsMode = StubRunnerProperties.StubsMode.LOCAL)</code></p>
</div>
<div class="paragraph">
<p>Now you can run the tests and see them tests pass!</p>
</div>
<div class="paragraph">
<p>For this example, we scan the following locations by default:
* <code>/META-INF/com.example/beer-api-producer-restdocs/<strong>/<strong>.</strong></code>
* <code>/contracts/com.example/beer-api-producer-restdocs/</strong>/<strong>.</strong></code>
* <code>/mappings/com.example/beer-api-producer-restdocs/<strong>*/</strong>.*</code></p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_solutions">Solutions</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_written_consumer_tests">Written consumer tests</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	@Test
	public void should_give_me_a_beer_when_im_old_enough() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/beer")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 22)).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().string("THERE YOU GO"));
		//remove::end[]
	}

	@Test
	public void should_reject_a_beer_when_im_too_young() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/beer")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 17)).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().string("GET LOST"));
		//remove::end[]
	}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_adding_spring_cloud_contract_dependency">Adding Spring Cloud Contract Dependency</h3>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
	&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
	&lt;artifactId&gt;spring-cloud-starter-contract-verifier&lt;/artifactId&gt;
	&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testCompile("org.springframework.cloud:spring-cloud-starter-contract-verifier")</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_proposal_of_simple_contracts_by_consumer">Proposal of simple contracts by consumer</h3>
<div class="paragraph">
<p><strong>HTTP communication</strong></p>
</div>
<div class="listingblock primary">
<div class="title">Old Enough</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// rest/shouldGrantABeerIfOldEnough.groovy
org.springframework.cloud.contract.spec.Contract.make {
		description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```

""")
	request {
		method 'POST'
		url '/check'
		body(
				age: 22,
				name: "marcin"
		)
		headers {
			contentType(applicationJson())
		}
	}
	response {
		status 200
		body("""
			{
				"status": "OK"
			}
			""")
		headers {
			contentType(applicationJson())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Too Young</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// rest/shouldRejectABeerIfTooYoung.groovy
org.springframework.cloud.contract.spec.Contract.make {
		description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```

""")
	request {
		method 'POST'
		url '/check'
		body(
				age: 17,
				name: "marcin"
		)
		headers {
			contentType(applicationJson())
		}
	}
	response {
		status 200
		body("""
			{
				"status": "NOT_OK"
			}
			""")
		headers {
			contentType(applicationJson())
		}
	}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Messaging communication</strong></p>
</div>
<div class="listingblock primary">
<div class="title">Positive Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendAcceptedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a positive verification message when person is eligible to get the beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll send a message with a positive verification
```

""")
	// Label by means of which the output message can be triggered
	label 'accepted_verification'
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: true
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Negative Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendRejectedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a negative verification message when person is not eligible to get the beer

```
given:
	client is too young
when:
	he applies for a beer
then:
	we'll send a message with a negative verification
```

""")
	// Label by means of which the output message can be triggered
	label 'rejected_verification'
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: false
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_consumer_controller_code">Missing consumer controller code</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		ResponseEntity&lt;Response&gt; response = this.restTemplate.exchange(
				RequestEntity
						.post(URI.create("http://localhost:" + this.port + "/check"))
						.contentType(MediaType.APPLICATION_JSON)
						.body(person),
				Response.class);
		switch (response.getBody().status) {
		case OK:
			return "THERE YOU GO";
		default:
			return "GET LOST";
		}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_stub_logs">Stub Logs</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">2017-05-11 12:16:51.146  INFO 4693 --- [           main] o.s.c.c.s.StubDownloaderBuilderProvider  : Will download stubs using Aether
2017-05-11 12:16:51.148  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Remote repos not passed but the switch to work offline was set. Stubs will be used from your local Maven repository.
2017-05-11 12:16:51.291  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Desired version is [+] - will try to resolve the latest version
2017-05-11 12:16:51.308  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved version is [0.0.1-SNAPSHOT]
2017-05-11 12:16:51.309  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolving artifact [com.example:{producer_artifact}:jar:stubs:0.0.1-SNAPSHOT] using remote repositories []
2017-05-11 12:16:51.317  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved artifact [com.example:{producer_artifact}:jar:stubs:0.0.1-SNAPSHOT] to /home/marcin/.m2/repository/com/example/{producer_artifact}/0.0.1-SNAPSHOT/{producer_artifact}-0.0.1-SNAPSHOT-stubs.jar
2017-05-11 12:16:51.322  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Unpacking stub from JAR [URI: file:/home/marcin/.m2/repository/com/example/{producer_artifact}/0.0.1-SNAPSHOT/{producer_artifact}-0.0.1-SNAPSHOT-stubs.jar]
2017-05-11 12:16:51.327  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Unpacked file to [/tmp/contracts9053257535983128167]
2017-05-11 12:16:52.608  INFO 4693 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@699e0bf0: startup date [Thu May 11 12:16:52 CEST 2017]; root of context hierarchy
2017-05-11 12:16:52.684  INFO 4693 --- [           main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2017-05-11 12:16:52.837  INFO 4693 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8090 (http)
2017-05-11 12:16:52.851  INFO 4693 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2017-05-11 12:16:52.853  INFO 4693 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.14
2017-05-11 12:16:52.975  INFO 4693 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-05-11 12:16:52.975  INFO 4693 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 367 ms
2017-05-11 12:16:52.996  INFO 4693 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'stub' to [/]
2017-05-11 12:16:53.000  INFO 4693 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'admin' to [/__admin/*]
2017-05-11 12:16:53.135  INFO 4693 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8090 (http)
2017-05-11 12:16:53.139  INFO 4693 --- [           main] o.s.c.contract.stubrunner.StubServer     : Started stub server for project [com.example:{producer_artifact}:0.0.1-SNAPSHOT:stubs] on port 8090</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beer_request">Beer Request</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">class BeerRequest {
	public int age;

	public BeerRequest(int age) {
		this.age = age;
	}

	public BeerRequest() {
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_listener_code">Missing listener code</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		if (verification.eligible) {
			this.eligibleCounter.incrementAndGet();
		} else {
			this.notEligibleCounter.incrementAndGet();
		}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_triggers">Missing triggers</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	@Test public void should_increase_the_eligible_counter_when_verification_was_accepted() throws Exception {
		int initialCounter = this.listener.eligibleCounter.get();

		//remove::start[]
		this.stubTrigger.trigger("accepted_verification");
		//remove::end[]

		then(this.listener.eligibleCounter.get()).isGreaterThan(initialCounter);
	}

	@Test public void should_increase_the_noteligible_counter_when_verification_was_rejected() throws Exception {
		int initialCounter = this.listener.notEligibleCounter.get();

		//remove::start[]
		this.stubTrigger.trigger("rejected_verification");
		//remove::end[]

		then(this.listener.notEligibleCounter.get()).isGreaterThan(initialCounter);
	}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_messaging_dsls">Messaging DSLs</h3>
<div class="listingblock primary">
<div class="title">Positive Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendAcceptedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a positive verification message when person is eligible to get the beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll send a message with a positive verification
```

""")
	// Label by means of which the output message can be triggered
	label 'accepted_verification'
	// input to the contract
	input {
		// the contract will be triggered by a method
		triggeredBy('clientIsOldEnough()')
	}
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: true
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Negative Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendRejectedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a negative verification message when person is not eligible to get the beer

```
given:
	client is too young
when:
	he applies for a beer
then:
	we'll send a message with a negative verification
```

""")
	// Label by means of which the output message can be triggered
	label 'rejected_verification'
	// input to the contract
	input {
		// the contract will be triggered by a method
		triggeredBy('clientIsTooYoung()')
	}
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: false
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_producercontroller_implementation">ProducerController implementation</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">if (personCheckingService.shouldGetBeer(personToCheck)) {
    return new Response(BeerCheckStatus.OK);
}
return new Response(BeerCheckStatus.NOT_OK);</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beerrestbase">BeerRestBase</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(MockitoJUnitRunner.class)
public abstract class BeerRestBase {
	@Mock PersonCheckingService personCheckingService;
	@InjectMocks ProducerController producerController;

	@Before
	public void setup() {
		given(personCheckingService.shouldGetBeer(argThat(oldEnough()))).willReturn(true);
		RestAssuredMockMvc.standaloneSetup(producerController);
	}

	private TypeSafeMatcher&lt;PersonToCheck&gt; oldEnough() {
		return new TypeSafeMatcher&lt;PersonToCheck&gt;() {
			@Override protected boolean matchesSafely(PersonToCheck personToCheck) {
				return personToCheck.age &gt;= 20;
			}

			@Override public void describeTo(Description description) {

			}
		};
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beermessagingbase">BeerMessagingBase</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@AutoConfigureMessageVerifier
public abstract class BeerMessagingBase {
	@Inject MessageVerifier messaging;
	@Autowired PersonCheckingService personCheckingService;

	@Before
	public void setup() {
		// let's clear any remaining messages
		// output == destination or channel name
		this.messaging.receive("output", 100, TimeUnit.MILLISECONDS);
	}

	public void clientIsOldEnough() {
		personCheckingService.shouldGetBeer(new PersonToCheck(25));
	}

	public void clientIsTooYoung() {
		personCheckingService.shouldGetBeer(new PersonToCheck(5));
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_messaging_implementation">Messaging implementation</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		boolean shouldGetBeer = personToCheck.age &gt;= 20;
		this.source.output().send(MessageBuilder.withPayload(new Verification(shouldGetBeer)).build());
		return shouldGetBeer;</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_rest_docs_producer_tests_config">Rest Docs Producer Tests Config</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">    @Configuration
    @EnableAutoConfiguration
    static class Config {
        @Bean
        PersonCheckingService personCheckingService() {
            return personToCheck -&gt; personToCheck.age &gt;= 20;
        }

        @Bean
        ProducerController producerController(PersonCheckingService service) {
            return new ProducerController(service);
        }
    }</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_rest_docs_producer_tests">Rest Docs Producer Tests</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerControllerTests.Config.class)
@AutoConfigureRestDocs(outputDir = "target/snippets")
@AutoConfigureMockMvc
@AutoConfigureJsonTesters
@DirtiesContext
public class ProducerControllerTests {

	@Autowired private MockMvc mockMvc;

	private JacksonTester&lt;PersonToCheck&gt; json;

	@Before
	public void setup() {
		ObjectMapper objectMappper = new ObjectMapper();
		// Possibly configure the mapper
		JacksonTester.initFields(this, objectMappper);
	}

	@Test
	public void should_grant_a_beer_when_person_is_old_enough() throws Exception {
		PersonToCheck personToCheck = new PersonToCheck(34);
		mockMvc.perform(MockMvcRequestBuilders.post("/check")
				.contentType(MediaType.APPLICATION_JSON)
				.content(json.write(personToCheck).getJson()))
				.andExpect(jsonPath("$.status").value("OK"));
	}

	@Test
	public void should_reject_a_beer_when_person_is_too_young() throws Exception {
		PersonToCheck personToCheck = new PersonToCheck(10);
		mockMvc.perform(MockMvcRequestBuilders.post("/check")
				.contentType(MediaType.APPLICATION_JSON)
				.content(json.write(personToCheck).getJson()))
				.andExpect(jsonPath("$.status").value("NOT_OK"));
	}

	@Configuration
	@EnableAutoConfiguration
	static class Config {
		@Bean
		PersonCheckingService personCheckingService() {
			return personToCheck -&gt; personToCheck.age &gt;= 20;
		}

		@Bean
		ProducerController producerController(PersonCheckingService service) {
			return new ProducerController(service);
		}
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_rest_docs_producer_tests_with_contracts">Rest Docs Producer Tests with Contracts</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerControllerTests.Config.class)
@AutoConfigureRestDocs(outputDir = "target/snippets")
@AutoConfigureMockMvc
@AutoConfigureJsonTesters
@DirtiesContext
public class ProducerControllerTests {

	@Autowired private MockMvc mockMvc;

	private JacksonTester&lt;PersonToCheck&gt; json;

	@Before
	public void setup() {
		ObjectMapper objectMappper = new ObjectMapper();
		// Possibly configure the mapper
		JacksonTester.initFields(this, objectMappper);
	}

	@Test
	public void should_grant_a_beer_when_person_is_old_enough() throws Exception {
		PersonToCheck personToCheck = new PersonToCheck(34);
		mockMvc.perform(MockMvcRequestBuilders.post("/check")
				.contentType(MediaType.APPLICATION_JSON)
				.content(json.write(personToCheck).getJson()))
				.andExpect(jsonPath("$.status").value("OK"))
				.andDo(WireMockRestDocs.verify()
						.jsonPath("$[?(@.age &gt;= 20)]")
						.contentType(MediaType.valueOf("application/json"))
						.stub("shouldGrantABeerIfOldEnough"))
				.andDo(MockMvcRestDocumentation.document("shouldGrantABeerIfOldEnough",
						SpringCloudContractRestDocs.dslContract()));
	}

	@Test
	public void should_reject_a_beer_when_person_is_too_young() throws Exception {
		PersonToCheck personToCheck = new PersonToCheck(10);
		mockMvc.perform(MockMvcRequestBuilders.post("/check")
				.contentType(MediaType.APPLICATION_JSON)
				.content(json.write(personToCheck).getJson()))
				.andExpect(jsonPath("$.status").value("NOT_OK"))
				.andDo(WireMockRestDocs.verify()
						.jsonPath("$[?(@.age &lt; 20)]")
						.contentType(MediaType.valueOf("application/json"))
						.stub("shouldRejectABeerIfTooYoung"))
				.andDo(MockMvcRestDocumentation.document("shouldRejectABeerIfTooYoung",
						SpringCloudContractRestDocs.dslContract()));
	}

	@Configuration
	@EnableAutoConfiguration
	static class Config {
		@Bean
		PersonCheckingService personCheckingService() {
			return personToCheck -&gt; personToCheck.age &gt;= 20;
		}

		@Bean
		ProducerController producerController(PersonCheckingService service) {
			return new ProducerController(service);
		}
	}
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_back_to_the_main_page">Back to the Main Page</h2>
<div class="sectionbody">
<div class="paragraph">
<p><a href="../workshops.html">Click here to go back to the main page</a></p>
</div>
</div>
</div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js"></script>
<script>prettyPrint()</script>
</body>
</html>